#include "DAEFloat3.h"
#include "math.h"


DAEFloat3::DAEFloat3():x(0),y(0),z(0)
{
}

DAEFloat3::DAEFloat3(float xValue,float yValue, float zValue):x(xValue),y(yValue),z(zValue)
{
}

DAEFloat3::DAEFloat3(float xValue, float yValue, float zValue,bool normalize):x(xValue),y(yValue),z(zValue)
{
	if (normalize)
		Normalize();
}

void DAEFloat3::Normalize(){
	float length= sqrt( x*x+y*y+z*z);
	x/=length;
	y/=length;
	z/=length;
}

DAEFloat3& DAEFloat3::operator=(const DAEFloat3& float3)
{
	this->x=float3.x;
	this->y=float3.y;
	this->z=float3.z;
	return *this;
}

DAEFloat3::DAEFloat3(const DAEFloat3& float3)
{
	this->x=float3.x;
	this->y=float3.y;
	this->z=float3.z;
}

DAEFloat3& DAEFloat3::Add(DAEFloat3& outResult, const float scale, const DAEFloat3& vector) const
{
	float scalex = scale*vector.x;
	float scaley = scale*vector.y;
	float scalez = scale*vector.z;

	float rx = x + scalex;
	float ry = y + scaley;
	float rz = z + scalez;

	outResult.SetValues(rx,ry,rz);
	return outResult;	
}


DAEFloat3& DAEFloat3::Add(DAEFloat3& outResult,const DAEFloat3& position) const
{
	outResult.SetValues(x+position.x, y+position.y,z+position.z);
	return outResult;
}

DAEFloat3& DAEFloat3::Subtract(DAEFloat3& outResult,const DAEFloat3& position) const
{
	outResult.SetValues(x-position.x,y-position.y,z-position.z);
	return outResult;
}

DAEFloat3& DAEFloat3::CreateVector(DAEFloat3& outResult,const DAEFloat3& to) const
{
	float xr = to.x - x;
	float yr = to.y - y;
	float zr = to.z - z;
	outResult.SetValues(xr,yr,zr);
	return outResult;
}

DAEFloat3& DAEFloat3::CrossAndNormalize(DAEFloat3& outResult, const DAEFloat3& vector) const
{
	// a = b cross c
	// b = this
	// c = vector
	//a_x = b_y * c_z - b_z * c_y
    //a_y = b_z * c_x - b_x * c_z 
    //a_z = b_x * c_y - b_y * c_x 
	float xr = this->y * vector.z - this->z * vector.y;
	float yr = this->z * vector.x - this->x * vector.z;
	float zr = this->x * vector.y - this->y * vector.x;
	outResult.SetValues(xr,yr,zr);
	outResult.Normalize();
	return outResult;

}

float DAEFloat3::Dot(const DAEFloat3 & vector2) const
{
	return this->x*vector2.x + this->y*vector2.y + this->z*vector2.z;
}

DAEFloat3& DAEFloat3::Scale(DAEFloat3& outResult, const float scale) const
{
	outResult.SetValues(x*scale,y*scale,z*scale);
	return outResult;
}

void DAEFloat3::Clamp(float min, float max)
{
	if ( x > max )
		x = max;
	else if ( x < min)
		x = min;

	if ( y > max )
		y = max;
	else if ( y < min)
		y = min;

	if ( z > max )
		z = max;
	else if ( z < min)
		z = min;
}